<script lang="jsx">
import { deepClone } from '../../utils/index'
import { stringify, parse } from '../../utils/json'
import render from '../render/render.jsx'
import { formConf } from '../../config/index.js'
import { createIdAndKey } from '../../utils/componetConfig.js'
import {getTemplateById} from '../../api/template.js'
import {getTemplatesToCreateById,getWorkOrderInfo,getFillOut } from '../../api/order.js'
import ruleTrigger from '../generator/ruleTrigger.js'

/**
 * 用于判断当前页面是预览页还是编辑页面
 * 场景1：预览页下面 不显示tip 编辑页要显示
 * 场景2
 * @type {boolean}
 */
let isDisabled = false;

/**
 * 判断字符串是否为空
 * @param value
 * @returns {boolean}
 */
function isValueEmpty(value) {
  return value === undefined || value === null || value === '';
}
const layouts = {
  colFormItem(h, scheme, index) {
    // console.log('colFormItem arguments', arguments)
    const config = scheme.__config__
    const listeners = buildListeners.call(this, scheme)
    // 整个表单,和当前表单
    let forms = this[this.formConfCopy.formModel]
    let form = forms[index]

    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
    if (config.showLabel === false) labelWidth = '0'

    let itemClassItem = config.labelPosition === 'top' || this.isMobile ? 'el-form-item--label-top' : ''
    let span = config.span
    let child = renderChildren.apply(this, arguments)
    // console.log('this', this)
    let showLabel = ()=>{
      return config.showLabel ? config.label : ''
    }
    let visible = true
    // console.log(scheme,card)
    return (
      <div>
        {visible && (
          <el-col span={span}>
            <el-form-item
              label-width={labelWidth}
              prop={scheme.__vModel__}
              label={showLabel()}
              class={itemClassItem}
            >
              {(isShowEmpty(scheme)) ?(
                // 如果禁用且默认值为空，则渲染无为_无对应的表单项 场景 详情页 预览页
                <div class="el-form-item__tip">{scheme.__config__.emptyContent || `无${scheme.__config__.label}`}</div>
              ):(
                // 如果不禁用，则正常渲染当前表单控件 (不禁用是指当前页面是可编辑表单页面 如创建工单 活动 策划等页面)
                <render conf={scheme} on={listeners} form={form} forms={forms}>
                  {child}
                </render>
              )}
              {config.tip && (
                // 如果不禁用，如果存在tip提示 则渲染
                <div class="el-form-item__tip">{config.tip}</div>
              )}
            </el-form-item>
          </el-col>
        )}
      </div>
    );
  },
  rowFormItem(h, scheme, index) {
    let child = renderChildren.apply(this, arguments)
    if (scheme.type === 'flex') {
      child = <el-row type={scheme.type} justify={scheme.justify} align={scheme.align}>
              {child}
            </el-row>
    }
    return (
      <el-col span={scheme.span}>
        <el-row gutter={scheme.gutter}>
          {child}
        </el-row>
      </el-col>
    )
  },
  raw(h, scheme) {
    const child = renderChildren.apply(this, arguments)
    const listeners = buildListeners.call(this, scheme)
    return (
      <render conf={scheme} on={listeners}>{child}</render>
    )
  },
  tsCard(h, scheme ,index, $scopedSlots) {
    const { formConfCopy } = this
    const cardHeader = renderChildren.apply(this, scheme, scheme.__config__.children.cardHeader)
    const cardBody = renderChildren.apply(this, scheme, scheme.__config__.children.cardBody)
    return (
      <el-col span={scheme.span}>
        <el-row gutter={this.formConfCopy.gutter}>
          <el-card className="box-card" shadow="never">
            <div slot="header" className="clearfix">
              {cardHeader}
            </div>
            <div>{cardBody}</div>
          </el-card>
        </el-row>
      </el-col>
    )
  }
}

function renderTabsChildren(h, scheme, a) {
  const config = scheme.children
  if (!Array.isArray(config)) return null
  return renderFormItem.call(this, h, config)
}

function renderForm(h, $scopedSlots) {
  const { formConfCopy } = this
  let getForm = (model, rules, fields, index, $scopedSlots)=>{
    // 如果不显示组件,也保证refs有数据
    return (<el-form
      size={formConfCopy.size}
      label-position={formConfCopy.labelPosition}
      label-width={`${formConfCopy.labelWidth}px`}
      ref={formConfCopy.formRef+index}
      // model不能直接赋值 https://github.com/vuejs/jsx/issues/49#issuecomment-472013664
      props={{ model }}
      rules={rules}
      on={{
        submit: event => {
          event.preventDefault();
        }
      }}
    >
      {renderFormItem.call(this, h, fields, index, $scopedSlots)}
    </el-form>)
  }
  let formModel = this[formConfCopy.formModel]
  let formRules = this[formConfCopy.formRules]
  let fields = formConfCopy.fields
  // console.log('renderForm-formModel',formModel)
  return (
    <el-row gutter={formConfCopy.gutter}>
      {formModel.map((t,i)=>{
        return getForm(t, formRules[i], [fields[i]], i, $scopedSlots)
      })}
    </el-row>
  )
}

function renderFormItem(h, elementList, index, $scopedSlots) {
  // console.log('elementList', elementList)
  return elementList.map(scheme => {
    // console.log('scheme', scheme)
    const config = scheme.__config__
    const layout = layouts[config.layout]
    if (layout) {
      return layout.call(this, h, scheme, index, $scopedSlots)
    }
    throw new Error(`没有与${config.layout}匹配的layout`)
  })
}

function renderChildren(h, scheme, children) {
  const config = scheme.__config__
  if(!children) {
    children = config.children
  }
  // console.log('scheme', scheme)
  // console.log('children-1', children)
  if (!Array.isArray(children)) return null
  return children.map((el, i) => {
    const layout = layouts[el.__config__.layout]
    if (layout) {
      // return layout.call(this, h, el, i, config.children)
      return layout.call(this, h, el, i)
    }
    return renderFormItem.call(this, h, children)
  })
}

function setValue(event, config, scheme) {
  // console.log('event', event)
  // console.log('config',config)
  // console.log('scheme',scheme)
  this.$set(config, 'defaultValue', event)
  let formModel = this[this.formConfCopy.formModel]
  // console.log('formModel',formModel)
  formModel.forEach(item => {
    if (Object.keys(item).includes(scheme.__vModel__)) {
      this.$set(item, scheme.__vModel__, event)
    }
  })
}

function buildListeners(scheme) {
  const config = scheme.__config__
  const methods = this.formConfCopy.__methods__ || {}
  const listeners = {}
  // 给__methods__中的方法绑定this和event
  Object.keys(methods).forEach(key => {
    listeners[key] = event => methods[key].call(this, event)
  })
  // 响应 render.js 中的 vModel $emit('input', val)
  listeners.input = event => setValue.call(this, event, config, scheme)

  return listeners
}

export default {
  components: {
    render
  },
  props: {
    disabled: {
      type: Boolean,
      default: false
    },
  },
  data() {
    let formConfCopy = deepClone({
      ...formConf
    })
    let {formModel, formRules} = formConfCopy
    return {
      formConfCopy,
      [formModel]: [],
      [formRules]: [],
      formRefs: [],
      watchList: [], //取消侦听器函数列表
    }
  },
  computed: {
  },
  created(){
  },
  mounted(){
  },
  watch: {
  },
  destroyed() {
    // console.log('destroyed')
    this.unWatch()
  },
  methods: {
    findField(__vModel__){
      for(let i = 0;i<this.formConfCopy.fields.length;i++){
        let cur = this.formConfCopy.fields[i]
        const config = cur.__config__
        if (config.tag === 'el-card' && config.children?.cardBody) {
          for(let j = 0;j<config.children.cardBody.length;j++){
            let field = config.children.cardBody[j]
            if(field.__vModel__ === __vModel__){
              return field
            }
          }
        }
      }
    },
    unWatch(){
      // console.log('unWatch.length', this.watchList.length)
      this.watchList.forEach(t=>t())
      this.watchList = []
    },
    initWatch(){
      try{
        let formModel = this.formConfCopy.formModel
        // console.log('initWatch')
        // console.log('form', this[formModel])
        if(this[formModel] && Array.isArray(this[formModel])){
          this[formModel].forEach((item, index)=>{
            for(let key in item){
              let unWatch = this.$watch(`${formModel}.${index}.${key}`,(value)=>{
                // console.log(`watch-${formModel}.${index}.${key}`, value)
                this.$emit('change', {...item, value})
              })
              this.watchList.push(unWatch)
            }
          })
        }
        // console.log('init-watchList.length', this.watchList.length)
      }catch(error){
        console.error(error)
      }
    },
    // 对接业务系统,根据业务需要的数据
    async setModules(data){
      // 取消侦听器
      this.unWatch()
      data = deepClone(data)
      this.formConf.fields = data
      this.formConfCopy = deepClone({
        ...this.formConfCopy,
        data
      })
      let {formModel, formRules, fields} = this.formConfCopy
      this[formModel] = []
      this[formRules] = []
      this.initFormData(fields, this[formModel])
      this.buildRules(fields, this[formRules])
      await this.$nextTick()
      this.initFormRefs()
      this.initWatch()
    },
    initCards(componentList, cards){
      if (Array.isArray(componentList)) {
        componentList.forEach((cur,i) => {
          cards.push({
            ...cur,
            $refs: {}
          })
        })
      }
    },
    initFormRefs(){
      this.formRefs = []
      for(var key in this.$refs){
        let item = this.$refs[key]
        if(item && item.$options.name === 'ElForm'){
          // console.log('item', item)
          const computedStyle = window.getComputedStyle(item.$el);
          if (computedStyle.display !== 'none' && item.disabled !== true) {
            this.formRefs.push(item)
          }
        }
      }
    },
    initFormData(componentList, formData) {
      // console.log('formData', formData)
      if (Array.isArray(componentList)) {
        componentList.forEach(cur => {
          // console.log('cur', cur)
          const config = cur.__config__
          if (config.tag === 'ts-sub-form') {
            config.defaultValue = [{ field102: '111', field103: '222' }, { field102: '333', field103: '444' }]
            formData[config.formId] = config.defaultValue
          } else if (config.tag === 'el-card') {
            let subFormData = {}
            if (config.children?.cardHeader) this.initFormData(config.children.cardHeader, subFormData)
            if (config.children?.cardBody) this.initFormData(config.children.cardBody, subFormData)
            formData.push(subFormData)
          } else {
            if (cur.__vModel__) formData[cur.__vModel__] = config.defaultValue
          }
        })
      } else {
        componentList.cardBody.forEach(cur => {
          const config = cur.__config__
          if (cur.__vModel__) formData[cur.__vModel__] = config.defaultValue
          if (config.children) this.initFormData(config.children, formData)
        })
      }
    },
    buildRules(componentList, rules) {
      if (Array.isArray(componentList)) {
        componentList.forEach(cur => {
          const config = cur.__config__
          if (config.tag === 'el-card') {
            let subRules = {}
            if (config.children?.cardHeader) this.buildRules(config.children.cardHeader, subRules)
            if (config.children?.cardBody) this.buildRules(config.children.cardBody, subRules)
            rules.push(subRules)
          } else {
            let regList = []
            if (config.required) {
              // , message: cur.placeholder
              const item = { required: config.required }
              if (Array.isArray(config.defaultValue)) {
                item.type = 'array'
                item.message = `请至少选择一个${config.label}`
              }
              item.message === undefined && (item.message = `${config.label}不能为空`)
              regList.push(item)
            }
            if (config.validator){
              config.validator = config.validator.bind({
                config
              })
              const item = { validator: config.validator }
              regList.push(item)
              // console.log('config',config, 'regList', regList)
            }
            rules[cur.__vModel__] = regList.map(item => {
              item.pattern && (item.pattern = eval(item.pattern))
              item.trigger = ruleTrigger && ruleTrigger[config.tag]
              return item
            })
          }
          if (config.children) this.buildRules(config.children, rules)
        })
      }
    },
    onReset() {
      let formRef = this.$refs[this.formConfCopy.formRef]
      formRef.forEach(t=> t.resetFields())
    },
    getModules(){
      let keyValue = []
      let getItem = (i)=>{
        let currentForm = this[this.formConfCopy.formModel][i]
        // console.log('currentForm',currentForm)
        let keys = Object.keys(currentForm)
        keys.forEach(key=> {
          // 生成content
          let field = this.findField(key)
          let value =  currentForm[key]
          keyValue.push({
            key,
            value,
          })
        })
      }
      let {fields} = this.formConf
      fields.forEach((m,i)=>{
        getItem(i)
      })
      return {
        fields,
        keyValue
      }
    },
    validateItems(){
      return new Promise(async (resolve,reject)=>{
        let checkStatusResult = false
        try {
          let l = [
            ...this.formRefs.map(t=>t.validate()),
          ]
          await Promise.all(l)
          checkStatusResult = true
        } catch (error) {
          console.error(error)
        }
      })
    },
    async validate(isValidate = true){
      if(isValidate){
        await this.validateItems()
      }
      let modules = this.getModules()
      return modules
    },
  },
  render(h) {
    return (
      <div  class={{ 'form-parser': true }}>
        {renderForm.call(this, h, this.$scopedSlots)}
      </div>
    )
  }
}
</script>
<style lang="scss" scoped>
::v-deep .el-card__body:after{
   content: ""; display: table; clear: both;
}
.left {
  margin-right: 10px;
}
.center {
  flex:1;width: 100%;
}
// 第二个.el-card开始的margin-top为10
// :nth-child(n+2)
.center .el-row .el-form {
  &:before,&:after{
    content: '';
    display: table;
    clear: both;
  }
  &:nth-child(n+2){
    margin-top: 10px;
  }
}
@media (max-width: 767.98px) {
  .center {
    > .el-row {
      margin-right: 0 !important;
      margin-left: 0 !important;
    }
  }
}
</style>
